#define ZCORE_SOURCE
#include "BraceNode.hpp"
#include "BraceFile.hpp"
#include "Log.hpp"

namespace zzz{

BraceNode::BraceNode(const BraceNode &node)
:item(node.item),parent(node.parent),idx(node.idx)
{}

BraceNode::BraceNode(BraceItem *_item,BraceItem *_parent,int i)
:item(_item),parent(_parent),idx(i)
{}

bool BraceNode::IsValid() const
{
  return item!=NULL;
}

zuint BraceNode::NodeNumber() const
{
  return item->children_.size();
}

BraceNode BraceNode::GetNode(zuint n)
{
  ZCHECK_LT(n, NodeNumber())<<"BraceNode::GetNode subsript overflow!";
  return BraceNode(item->children_[n],item, n);
}

bool OptionFind(const string &line, const string &opt)
{
  istringstream iss(line);
  string part;
  while(true)
  {
    iss>>part;
    if (iss.fail()) return false;
    if (part==opt) return true;
  }
  return false;
}

BraceNode BraceNode::AppendNode(const string &str, const char h, const char t) const
{
  item->AddNode(str.c_str(), h, t);
  return BraceNode(item->children_.back(),item,item->children_.size()-1);
}


bool BraceNode::HasNode(const string &str)
{
  for (vector<BraceItem*>::iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
  {
    const string &t=(*vi)->text_;
    if (OptionFind(t,str)) return true;
  }
  return false;
}

bool BraceNode::RemoveNode(zuint i)
{
  ZCHECK_LT(i, NodeNumber())<<"BraceNode::RemoveNode subsript overflow!";
  item->children_.erase(item->children_.begin()+i);
  return true;
}

zzz::BraceNode BraceNode::GetFirstNode(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
    {
      return BraceNode(*vi,item,vi-item->children_.begin());
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (t==str) return BraceNode(*vi,item,vi-item->children_.begin());
    }
  }
  return BraceNode(NULL,NULL, -1);
}

zzz::BraceNode BraceNode::GetNextSibling(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      return BraceNode(*vi,parent,vi-parent->children_.begin());
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (t==str) return BraceNode(*vi,parent,vi-parent->children_.begin());
    }
  }
  return BraceNode(NULL,NULL, -1);
}

void BraceNode::GotoNextSibling(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      item=*vi;idx=vi-parent->children_.begin();return;
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (t==str) {item=*vi;idx=vi-parent->children_.begin();return;}
    }
  }
  item=NULL;parent=NULL;idx=-1;
}

zzz::BraceNode BraceNode::GetFirstNodeInclude(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
    {
      return BraceNode(*vi,item,vi-item->children_.begin());
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (OptionFind(t,str)) return BraceNode(*vi,item,vi-item->children_.begin());
    }
  }
  return BraceNode(NULL,NULL, -1);
}

zzz::BraceNode BraceNode::GetNextSiblingInclude(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      return BraceNode(*vi,parent,vi-parent->children_.begin());
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (OptionFind(t,str)) return BraceNode(*vi,parent,vi-parent->children_.begin());
    }
  }
  return BraceNode(NULL,NULL, -1);
}

void BraceNode::GotoNextSiblingInclude(const string &str)
{
  if (str.empty())
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      item=*vi;idx=vi-parent->children_.begin();return;
    }
  }
  else
  {
    for (vector<BraceItem*>::iterator vi=parent->children_.begin()+idx+1;vi!=parent->children_.end();vi++)
    {
      const string &t=(*vi)->text_;
      if (OptionFind(t,str)) {item=*vi;idx=vi-parent->children_.begin();return;}
    }
  }
  item=NULL;parent=NULL;idx=-1;
}

void BraceNode::operator++()
{
  GotoNextSibling();
}

char BraceNode::GetHeadBrace()
{
  return item->head_;
}

char BraceNode::GetTailBrace()
{
  return item->tail_;
}

void BraceNode::SetHeadTail(char h, char t)
{
  item->head_=h;
  item->tail_=t;
}

const string& BraceNode::GetText() const
{
  return item->text_;
}

void BraceNode::SetText(const string &str)
{
  item->text_=str;
}

void BraceNode::GetChildrenText(string &str) const
{
  str.clear();
  for (vector<BraceItem*>::const_iterator vi=item->children_.begin();vi!=item->children_.end();vi++)
  {
    str+=(*vi)->text_;
    str+="\n";
  }
}


}